package com.zh.note.leetcode.dp;

/**
 * 01背包
 * 有n件物品和一个最多能背重量为w 的背包。
 * 第i件物品的重量是weight[i]，得到的价值是value[i] 。
 * 每件物品只能用一次，求解将哪些物品装入背包里物品价值总和最大。
 */
public class Bags_01 {


    public static int bagProblem(int[] weight, int[] value, int bagSize) {

        // 创建dp数组
        int goods = weight.length;  // 获取物品的数量
        int[][] dp = new int[goods][bagSize + 1];

        // 初始化dp数组
        // 创建数组后，其中默认的值就是0
        for (int j = weight[0]; j <= bagSize; j++) {
            dp[0][j] = value[0];
        }
        for (int i = 1; i < weight.length; i++) { // 遍历物品
            for (int j = 1; j <= bagSize; j++) { // 遍历背包容量
                if (j < weight[i]) {
                    /**
                     * 当前背包的容量都没有当前物品i大的时候，是不放物品i的
                     * 那么前i-1个物品能放下的最大价值就是当前情况的最大价值
                     */
                    dp[i][j] = dp[i - 1][j];
                } else {
                    /**
                     * 当前背包的容量可以放下物品i
                     * 那么此时分两种情况：
                     *    1、不放物品i
                     *    2、放物品i
                     * 比较这两种情况下，哪种背包中物品的最大价值最大
                     */
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
                }
            }
        }
        return dp[goods - 1][bagSize];

    }

    public static int bagProblem2(int[] weight, int[] value, int bagWight) {
        //定义dp数组：dp[j]表示背包容量为j时，能获得的最大价值
        int[] dp = new int[bagWight + 1];
        //初始化，全部初始化0

        for (int i = 0; i < weight.length; i++) {
            for (int j = bagWight; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        ArraysUtils.printArray(dp);
        return dp[bagWight];
    }

    public static void main(String[] args) {

        int[] weight = {1, 3, 4};
        int[] value = {15, 20, 30};
        int bagWight = 4;
        System.out.println(bagProblem2(weight, value, bagWight));
    }
}
